
//////// theGame.cpp /////////////////////////////////////////////////////
//    Author:   Richard (richard.lindholm85@gmail.com)                  //
//    Project:  some game project                                       //
//    Purpose:  The applications main class, used for almost everything //
//////////////////////////////////////////////////////////////////////////

//#include <string>
#include <cstdlib>
#include <ctime>
#include "theGame.h"

cTheGame::cTheGame()
{
    m_bDebugMode = false;
    m_pInput = NULL;
    m_pD3D = NULL;
    m_hunterPosX = m_hunterPosY = 0.0f;
}

cTheGame::~cTheGame()
{
    deleteApp();
}

bool cTheGame::initiateApp(HWND hWnd, HINSTANCE hInstance)
{
    srand((int)time(0));
    m_hWnd = hWnd;
    m_hInstance = hInstance;
    
    // initialize Direct3D
    m_pD3D = new myD3D(m_hWnd, m_hInstance);
    // initialize Input
    m_pInput = new cInput(m_hWnd, m_hInstance);

    // initialize Object handler
    m_objHandler = new cObjectHandler();
    //m_pObject = new cGameObject();
    //m_pPlayers = new cPlayer();

    m_objHandler->newPlayer(300, 0, 64, 64, "Nisse");

    if (!loadTextures())
        return false;

    return true;
}

void cTheGame::deleteApp()
{
    m_hWnd = 0;
    m_hInstance = 0;
    if (m_objHandler)
    {
        delete m_objHandler;
        m_objHandler = NULL;
    }
    if (m_pInput)
    {
        delete m_pInput;
        m_pInput = NULL;
    }
    if (m_pD3D)
    {
        delete m_pD3D;
        m_pD3D = NULL;
    }
}

bool cTheGame::loadTextures()
{
    // These are testing textures, nothing nice, just for testing
    //if (m_pD3D->AddTextureToList("Data\\Textures\\test_png.png") == -1)
    //    return false;
    //if (m_pD3D->AddTextureToList("Data\\Textures\\test_tiff.tif") == -1)
    //    return false;
    //if (m_pD3D->AddTextureToList("Data\\Textures\\test_bmp.bmp") == -1)
    //    return false;
    
    if (m_pD3D->AddTextureToList("Data\\Textures\\pointer.bmp") == -1)
        return false;
    if (m_pD3D->AddTextureToList("Data\\Textures\\kim.bmp") == -1)
        return false;
    if (m_pD3D->AddTextureToList("Data\\Textures\\tank.png") == -1)
        return false;
    if (m_pD3D->AddTextureToList("Data\\Textures\\sm.png") == -1)
        return false;

    
    if (m_pD3D->AddTextureToList("Data\\Textures\\test_png.png") == -1)
        return false;

    m_objHandler->newObject(INTPOINT(0, 0), INTPOINT(1, 1), TYPE_STATIC, "pointer");
    //m_objHandler->newObject(INTPOINT(0, 0), INTPOINT(4, 4), "kim");

    m_objHandler->newObject(INTPOINT(100, 10), INTPOINT(64, 64), TYPE_DYNAMIC, "kim01");
    m_objHandler->newObject(INTPOINT(200, 10), INTPOINT(64, 64), TYPE_DYNAMIC, "kim02");
    //m_objHandler->newObject(INTPOINT(300, 10), INTPOINT(64, 64), TYPE_DYNAMIC, "kim03");
    //m_objHandler->newObject(INTPOINT(400, 10), INTPOINT(64, 64), TYPE_DYNAMIC, "kim04");
    //m_objHandler->newObject(INTPOINT(100, 100), INTPOINT(64, 64), TYPE_DYNAMIC, "kim05");
    //m_objHandler->newObject(INTPOINT(200, 100), INTPOINT(64, 64), TYPE_DYNAMIC, "kim06");
    //m_objHandler->newObject(INTPOINT(300, 100), INTPOINT(64, 64), TYPE_DYNAMIC, "kim07");
    //m_objHandler->newObject(INTPOINT(400, 100), INTPOINT(64, 64), TYPE_DYNAMIC, "kim08");
    //m_objHandler->newObject(INTPOINT(300, 200), INTPOINT(64, 64), TYPE_DYNAMIC, "kim09");
    //m_objHandler->newObject(INTPOINT(200, 200), INTPOINT(64, 64), TYPE_DYNAMIC, "kim10");

    //m_objHandler->newObject(INTPOINT(100, 100), INTPOINT(256, 256), "sm");
    //m_objHandler->getObjectByName("sm")->bCanCollide = false;
    
    m_objHandler->newObject(INTPOINT(0, 386), INTPOINT(64, 64), TYPE_STATIC, "block01");
    m_objHandler->newObject(INTPOINT(64, 386), INTPOINT(64, 64), TYPE_STATIC, "block02");
    //m_objHandler->newObject(INTPOINT(128, 386), INTPOINT(64, 64), TYPE_STATIC, "block03");
    m_objHandler->newObject(INTPOINT(200, 386), INTPOINT(64, 64), TYPE_STATIC, "block04");
    m_objHandler->newObject(INTPOINT(256, 386), INTPOINT(64, 64), TYPE_STATIC, "block05");
    m_objHandler->newObject(INTPOINT(320, 386), INTPOINT(64, 64), TYPE_STATIC, "block06");
    m_objHandler->newObject(INTPOINT(0, 322), INTPOINT(64, 64), TYPE_STATIC, "block07");
    m_objHandler->newObject(INTPOINT(150, 200), INTPOINT(64, 64), TYPE_STATIC, "block08");


    // edge of the screen
    m_objHandler->newObject(INTPOINT(-1, -10), INTPOINT(602, 10), TYPE_STATIC, "SCREEN_TOP");
    m_objHandler->newObject(INTPOINT(-10, -1), INTPOINT(10, 452), TYPE_STATIC, "SCREEN_LEFT");
    m_objHandler->newObject(INTPOINT(-1, 450), INTPOINT(602, 10), TYPE_STATIC, "SCREEN_BOTTOM");
    m_objHandler->newObject(INTPOINT(600, -1), INTPOINT(10, 452), TYPE_STATIC, "SCREEN_RIGHT");


    return true;
}

void cTheGame::tick()
{
    update();
    updateInput();
    updateLogic();
    updateText();
    renderAll();
}

bool cTheGame::update()
{
    m_pInput->updateInput();

    POINT mPos;
    mPos.x = (LONG)m_pInput->getMouseX();
    mPos.y = (LONG)m_pInput->getMouseY();


    m_pD3D->ClearRenderList();

    m_objHandler->setCurrentPlayer("Nisse");
    m_pD3D->AddToRenderList(RenderData(2, D3DXVECTOR3((float)CurrentPlayer->getPos().X, (float)CurrentPlayer->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), HIG_PRIO);

    m_objHandler->setCurrentObject("pointer");
    CurrentObject->setPos((int)mPos.x, (int)mPos.y);
    m_pD3D->AddToRenderList(RenderData(0, D3DXVECTOR3((float)mPos.x, (float)mPos.y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MOUSE_PRIO);
    //m_pObject->setCurrentObject("kim");
    //m_pObject->setPos((int)m_hunterPosX, (int)m_hunterPosY);
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3(m_hunterPosX - 32.0f, m_hunterPosY - 32.0f, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), HIG_PRIO);
    
    m_objHandler->setCurrentObject("kim01");
    m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("kim02");
    m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim03");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim04");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim05");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim06");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim07");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim08");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim09");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //m_pObject->setCurrentObject("kim10");
    //m_pD3D->AddToRenderList(RenderData(1, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    //
    //m_pObject->setCurrentObject("sm");
    //m_pD3D->AddToRenderList(RenderData(3, D3DXVECTOR3((float)m_pObject->getPos().X, (float)m_pObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    
    m_objHandler->setCurrentObject("block01");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block02");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block03");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block04");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block05");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block06");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block07");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    m_objHandler->setCurrentObject("block08");
    m_pD3D->AddToRenderList(RenderData(4, D3DXVECTOR3((float)CurrentObject->getPos().X, (float)CurrentObject->getPos().Y, 0.0f), 0xFFFFFFFF, TYPE_SPRITE), MID_PRIO);
    

    return true;
}

void cTheGame::updateText()
{
    m_pD3D->SetTextColor(D3DXCOLOR(128.0f, 128.0f, 128.0f, 255.0f));

    if (m_bDebugMode)
    {
        m_pD3D->PrintText(10, 10, "Debug Text:");
        
        //char *cBuf = new char;
        //sprintf(cBuf, "Mouse: %i, %i", m_pInput->getMouseX(), m_pInput->getMouseY());
        m_pD3D->PrintText(10, 30, "Mouse: %i, %i", m_pInput->getMouseX(), m_pInput->getMouseY());
        m_pD3D->PrintText(10, 50, "Kim: %i", m_objHandler->getObjectByName("kim01")->getCollide());
        m_pD3D->PrintText(10, 70, "Block: %i", m_objHandler->getObjectByName("block08")->getCollide());

        //m_pD3D->PrintText(10, 50, "Kim04: %i, %i", m_pObject->getObjectByName("kim04")->pos.X, m_pObject->getObjectByName("kim04")->pos.Y);
        //OBJECT * obj = m_pObject->getObjectByName("kim01");

        //m_pD3D->PrintText(10, 50, "Kim: %i, %i, %i, %i", CurrentObject->getPos().X, CurrentObject->getPos().Y, (int)CurrentObject->getState(), (int)CurrentObject->getCollide());
        
        m_pD3D->PrintText(400, 50, "Pos: %i, %i", CurrentPlayer->getPos().X, CurrentPlayer->getPos().Y);
        m_pD3D->PrintText(400, 70, "Vel: %i, %i", (int)CurrentPlayer->getVelocity().X, (int)CurrentPlayer->getVelocity().Y);
        m_pD3D->PrintText(400, 90, "Col: %i", (int)CurrentPlayer->getCollide());
    }
    else
    {
        m_pD3D->PrintText(10, 10, "No Debug");
    }

    if (m_objHandler->getNumPlayers() > 0)
    {
        m_pD3D->PrintText(400, 10, "Player: %s", CurrentPlayer->getName().c_str());
        m_pD3D->PrintText(400, 30, "HP: %i", (int)CurrentPlayer->getHP());
    }
    
//    std::string str = "test";
//    m_pD3D->PrintText(200, 24, str.c_str());

}

void cTheGame::updateInput()
{
    if (m_pInput->isKeyDown(DIK_D))
    {
        CurrentPlayer->setVelocityX(5.0f);
        if (CurrentPlayer->getPlayerState() != PSTATE_JUMPING)// && m_pPlayers->getVelocity().Y == 0)
            CurrentPlayer->setPlayerState(PSTATE_RUNNING);
    }
    if (m_pInput->isKeyDown(DIK_A))
    {
        CurrentPlayer->setVelocityX(-5.0f);
        if (CurrentPlayer->getPlayerState() != PSTATE_JUMPING)// && m_pPlayers->getVelocity().Y == 0)
            CurrentPlayer->setPlayerState(PSTATE_RUNNING);
    }
    if (m_pInput->isKeyDown(DIK_SPACE) && CurrentPlayer->getVelocity().Y >= 0.0f && CurrentPlayer->getPlayerState() != PSTATE_JUMPING)
    {
        CurrentPlayer->setVelocityY(-10.0f);
        CurrentPlayer->setPlayerState(PSTATE_JUMPING);
    }
}

bool cTheGame::updateLogic()
{
    //POINT mousePos;
    //mousePos.x = m_pInput->getMouseX();
    //mousePos.y = m_pInput->getMouseY();

    /*
    if (m_pObject->isColliding(m_pObject->getObjectByName("pointer"), m_pObject->getObjectByName("kim")))
    {
        m_pD3D->PrintText(200, 200, "AKTA KIMS NASA!!");
        //m_hunterPosX = m_hunterPosY = 0.0f;
        //m_pObject->setCurrentObject("kim");
        //m_pObject->setPos((int)m_hunterPosX + 30, (int)m_hunterPosY + 30);
    }

    
    float deltaX = m_hunterPosX - (float)mousePos.x;
    float deltaY = m_hunterPosY - (float)mousePos.y;

    float finalDelta = sqrt((deltaX * deltaX) + (deltaY * deltaY));
    
    float x = deltaX * (1.0f / finalDelta);
    float y = deltaY * (1.0f / finalDelta);

    m_hunterPosX -= x * (finalDelta / 10); //(-deltaX / 10);
    m_hunterPosY -= y * (finalDelta / 10); //(-deltaY / 10);
    
    if (m_hunterPosX < 32) m_hunterPosX = 32;
    if (m_hunterPosY < 32) m_hunterPosY = 32;
    if (m_hunterPosX > 568) m_hunterPosX = 568;
    if (m_hunterPosY > 418) m_hunterPosY = 418;
    */
    
    makeObjectFlee("kim01");
    makeObjectFlee("kim02");
    //makeObjectFlee("kim03");
    //makeObjectFlee("kim04");
    //makeObjectFlee("kim05");
    //makeObjectFlee("kim06");
    //makeObjectFlee("kim07");
    //makeObjectFlee("kim08");
    //makeObjectFlee("kim09");
    //makeObjectFlee("kim10");
    //makeObjectFlee("sm");

    for (int i = 0; i < m_objHandler->getNumObjects(); i++)
    {
        if (m_objHandler->isColliding(CurrentPlayer, m_objHandler->getObjectAt(i)))
        {
            //m_pPlayers->getCurrentPlayer().second->velocity = FLOATPOINT(0.0f, 0.0f);
            CurrentPlayer->setPlayerState(PSTATE_IDLE);
        }
    }

    m_objHandler->updateObjects();
    m_objHandler->updatePlayers();

    return true;
}

void cTheGame::makeObjectFlee(std::string name)
{
    //int speed = 25;
    //INTPOINT mousePos;

    //mousePos.X = m_pObject->getObjectByName("pointer")->pos.X;
    //mousePos.Y = m_pObject->getObjectByName("pointer")->pos.Y;

    // objA will be checked against objB
    cGameObject *objA, *objB;

    m_objHandler->setCurrentObject(name);
    objA = m_objHandler->getObjectByName(name);

    if (objA->getType() == TYPE_DYNAMIC)
    {
        int randOne = (rand() % 4) + 1;
        int numberOfAdds = 0;
        FLOATPOINT newVel = FLOATPOINT(0.0f, 0.0f);
        for (int i = 0; i < m_objHandler->getNumObjects(); i++)
        {
            objB = m_objHandler->getObjectAt(i);

            if (objA->isCollidingWith(objB) && objA->getName() != objB->getName())
            {
                if (objB->getName() == string("pointer"))
                {
                    if (objA->getPos().X + (objA->getSize().X/2) < objB->getPos().X)
                        newVel.X += (objA->getPos().X + (objA->getSize().X/2) - objB->getPos().X) / 2;
                    else //if ((objA->getPos().X + objA->getSize().X)/2 > (objB->getPos().X + objB->getSize().X))
                        newVel.X += (objA->getPos().X + (objA->getSize().X/2) - objB->getPos().X) / 2;
                    if (objA->getPos().Y + (objA->getSize().Y/2) < objB->getPos().Y)
                        newVel.Y += (objA->getPos().Y + (objA->getSize().Y/2) - objB->getPos().Y) / 2;
                    else //if ((objA->getPos().Y + objA->getSize().Y)/2 > (objB->getPos().Y + objB->getSize().Y))
                        newVel.Y += (objA->getPos().Y + (objA->getSize().Y/2) - objB->getPos().Y) / 2;
                }
                //else
                //{
                //    if (objA->pos.X + (objA->size.X/2) < objB->pos.X)
                //        newVel.X += objB->velocity.X;
                //    else //if ((objA->pos.X + objA->size.X)/2 > (objB->pos.X + objB->size.X))
                //        newVel.X += objB->velocity.X;
                //    if (objA->pos.Y + (objA->size.Y/2) < objB->pos.Y)
                //        newVel.Y += objB->velocity.Y;
                //    else //if ((objA->pos.Y + objA->size.Y)/2 > (objB->pos.Y + objB->size.Y))
                //        newVel.Y += objB->velocity.Y;
                //}


                numberOfAdds++;

                //if (objA->pos.X < objB->pos.X + objB->size.X / 4 && objA->pos.X > objB->pos.X - objB->size.X / 4 &&
                //    objA->pos.Y < objB->pos.Y + objB->size.Y / 4 && objA->pos.Y > objB->pos.Y - objB->size.Y / 4)
                //{
                //    if (objB->pos.X > 536)
                //    {
                //        m_pObject->getObjectAt(i)->pos.X -= objB->size.X - randOne;
                //        m_pObject->getObjectAt(i)->pos.Y -= objB->size.Y - (rand() % 4);
                //        //m_pObject->getObjectAt(i)->pos.Y -= (rand() % 4) + 1;
                //    }
                //    else
                //    {
                //        m_pObject->getObjectAt(i)->pos.X += objB->size.X + randOne;
                //        m_pObject->getObjectAt(i)->pos.Y += objB->size.Y + (rand() % 4);
                //        //m_pObject->getObjectAt(i)->pos.Y += (rand() % 4) + 1;
                //    }
                //    //m_pObject->getObjectByName(name)->pos.X -= objA->size.X / 2;
                //}
            }

        }

        if (numberOfAdds != 0)
        {
            newVel.X /= numberOfAdds;// * randOne;
            newVel.Y /= numberOfAdds;// * ((rand() % 10) + 1);
            
            //if (newVel.X > 0) newVel.X += randOne; else newVel.X -= randOne;
            //if (newVel.Y > 0) newVel.Y += ((rand() % 10) + 1); else newVel.Y -= ((rand() % 10) + 1);
            //newVel.Y += 64;

            CurrentObject->setVelocity(newVel);
        }
    }

    
    //if (m_pObject->getPos().X < 0) m_pObject->setPos(1, m_pObject->getPos().Y);
    //else if (m_pObject->getPos().X > 600) m_pObject->setPos(599 - m_pObject->getSize().X, m_pObject->getPos().Y);
    //if (m_pObject->getPos().Y < 0) m_pObject->setPos(m_pObject->getPos().X, 1);
    //else if (m_pObject->getPos().Y > 450) m_pObject->setPos(m_pObject->getPos().X, 449 - m_pObject->getSize().Y);
}

bool cTheGame::renderAll()
{
    m_pD3D->render();

    return true;
}

//bool 
    
void cTheGame::setCmdLineStr(char * c)
{    
    m_cCmdLine = c;
    
    if (std::string(c).find("-debug") != std::string::npos)
    {
        m_bDebugMode = true;
    }
}
